package org.l.qiao.web.form;

import org.l.qiao.Cluster;
import org.l.qiao.Page;
import org.l.qiao.Validate;
import org.l.qiao.util.ClusterUtil;
import org.l.qiao.web.KeyUpdate;
import org.apache.log4j.Logger;
import org.l.qiao.annotation.Key;
import org.l.qiao.base.Convert;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by 严秋旺 on 2015/1/11.
 */
public class Form {

    private static final Logger LOGGER = Logger.getLogger(Form.class);

    private List<FormError> formErrors = new ArrayList<>();

    private HttpServletRequest request;

    public Form(HttpServletRequest request) {
        this.request = request;
    }

    public int getInteger(String param) {
        return getInteger(param, 0);
    }

    public int getInteger(String param, int defval) {
        String value = request.getParameter(param);
        int val = defval;

        if (value != null) {

            try {
                val = Integer.parseInt(value);
            } catch (Exception e) {
                val = defval;
                LOGGER.debug("参数转换整型异常：" + e.getMessage());
            }

        }

        return val;
    }

    public String getString(String param) {
        return getString(param, "");
    }

    public String getString(String param, String defval) {
        String value = request.getParameter(param);

        if (value == null) {
            value = defval;
        }

        return value;
    }

    public String[] getStrings(String param) {
        return request.getParameterValues(param);
    }

    public List getList(String param) {
        String[] values = request.getParameterValues(param);
        List<String> val = new ArrayList<>();

        for (String v : values) {
            val.add(v);
        }

        return val;
    }

    public boolean getCluster(Cluster cluster) {
        return getCluster(cluster, true, false);
    }

    public boolean getCluster(Cluster cluster, boolean format, boolean acceptWrong) {
        return getCluster(cluster, format, acceptWrong, null);
    }

    /**
     * 从表单接收数据簇
     *
     * @param cluster     待接收数据簇对象
     * @param format      是否进行值转换
     * @param acceptWrong 是否接收错误值
     * @param node        节点
     * @return 当所有值验证通过则返回true，否则false
     */
    public boolean getCluster(Cluster cluster, boolean format, boolean acceptWrong, String node) {
        formErrors.clear();
        boolean result = true;

        if (node == null) {
            node = "";
        } else {
            node = node + '.';
        }

        Map<String, Key> keys = ClusterUtil.keys(cluster.getClass());

        for (Map.Entry<String, Key> entry : keys.entrySet()) {
            Key annotation = entry.getValue();
            String keyPath = entry.getKey();
            String param = request.getParameter(node + keyPath);

            if (param == null) {

                if (!annotation.nullable()) {
                    result = false;
                    LOGGER.debug("参数[" + node + keyPath + "]为空，nullable=false");
                    FormError formError = new FormError();
                    formError.setName(node + keyPath);
                    formError.setNullable(false);
                    formError.setCheck(annotation.check());
                    formError.setValue(param);
                    formErrors.add(formError);
                }

                continue;
            }

            boolean checkResult = Validate.check(annotation.check(), param);
            result = checkResult ? result : false;

            if (checkResult || (!checkResult && acceptWrong)) {
                Object value = null;

                if (format) {

                    try {
                        value = Convert.parse(annotation, param);
                    } catch (Exception e) {
                        LOGGER.debug("值转换失败(" + param + ")：" + e);
                    }

                } else {
                    value = param;
                }

                ClusterUtil.put(cluster, keyPath, annotation.keyType(), value);
            } else {
                LOGGER.debug("参数[" + node + keyPath + "]=" + param + "，验证值[" + annotation.check() + "],acceptWrong=" + acceptWrong);
                FormError formError = new FormError();
                formError.setName(node + keyPath);
                formError.setNullable(annotation.nullable());
                formError.setCheck(annotation.check());
                formError.setValue(param);
                formErrors.add(formError);
            }

        }

        return result;
    }

    public boolean getBean(Object bean) {
        return getBean(bean, false);
    }

    public boolean getBean(Object bean, boolean acceptWrong) {
        return getBean(bean, acceptWrong, null);
    }

    /**
     * 从表单接收对象
     *
     * @param bean        待接收对象
     * @param acceptWrong 是否接收错误值
     * @param node        节点
     * @return 属性值验证结果，全部通过则返回true，否则返回false
     */
    public boolean getBean(Object bean, boolean acceptWrong, String node) {
        formErrors.clear();
        boolean result = true;

        if (node == null) {
            node = "";
        } else {
            node = node + '.';
        }

        Class beanClass = bean.getClass();
        Field[] properties = beanClass.getDeclaredFields();

        for (Field property : properties) {
            Key annotation = property.getAnnotation(Key.class);

            if (annotation == null) {
                continue;
            }

            String param = request.getParameter(node + property.getName());

            if (param == null) {

                if (!annotation.nullable()) {
                    result = false;
                    LOGGER.debug("参数[" + node + property.getName() + "]为空，nullable=false");
                }

                continue;
            }

            boolean checkResult = Validate.check(annotation.check(), param);
            result = checkResult ? result : false;

            if (checkResult || (!checkResult && acceptWrong)) {
                Object value = null;

                try {
                    value = Convert.parse(annotation, param);
                    String propertyName = property.getName();
                    String methodName = "set" + propertyName.substring(0, 1).toUpperCase() + propertyName.substring(1);
                    Method method = beanClass.getMethod(methodName, value.getClass());
                    method.invoke(bean, value);
                } catch (Exception e) {
                    LOGGER.debug("属性赋值异常[" + property + "](" + param + ")：" + e);
                }

            }
        }
        return result;
    }

    /**
     * 从表单获取分页对象
     *
     * @return 分页对象
     */
    public Page getPage() {
        Page page = new Page();
        getBean(page, false, "page");
        return page;
    }

    /**
     * 从表单获取键值修改对象
     *
     * @param clazz
     * @return
     */
    public KeyUpdate getKeyUpdate(Class clazz) {
        KeyUpdate keyUpdate = new KeyUpdate(clazz);
        getBean(keyUpdate, false, "update");
        return keyUpdate;
    }

    /**
     * 获取表单验证错误信息
     *
     * @return
     */
    public List<FormError> getFormErrors() {
        return formErrors;
    }

}
